package com.kb.medical.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kb.medical.config.ESClient;
import com.kb.medical.entity.Es;
import com.kb.medical.mapper.mp.EsMapper;
import com.kb.medical.service.es.EsService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.collapse.CollapseBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
//@RunWith：表示启动这个单元测试类(单元测试类是不能够运行的)，需要传递一个参数，必须是SpringRunner的实例类型
@RunWith(SpringRunner.class)
public class esTest1 {

    RestHighLevelClient client = ESClient.getClient();
    @Autowired
    private EsMapper esMapper;
    @Autowired
    private EsService esService;


//    @Test
//    public void run() {
//        GetIndexRequest request = new GetIndexRequest("user");
//        System.out.println(request);
//        // 发送请求，获取响应
//    }
//
//    @Test
//    public void updateDoc() throws IOException {
//
//        String index = "image";
//        String type = "_doc";
//
//
//        //1. 创建一个Map，指定需要修改的内容
//        Map<String, Object> doc = new HashMap<>();
//        doc.put("name", "张大三");
//        String docId = "1";
////2. 创建request对象，封装数据
//        UpdateRequest request = new UpdateRequest(index, type, docId);
//        request.doc(doc);
////3. 通过client对象执行
//
//        UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
//        System.out.println(update.getGetResult().toString());
//
//
//    }

    @Test
    public void json() {
        String json =
                "{\n" +
                        "  \"from\": 0,\n" +
                        "  \"size\": 6,\n" +
                        "  \"query\": {\n" +
                        "    \"function_score\": {\n" +
                        "      \"query\": {\n" +
                        "        \"multi_match\": {\n" +
                        "          \"query\": \"影像组学特征\",\n" +
                        "          \"fields\": [\"pdfText\", \"ocrText\"]\n" +
                        "        }\n" +
                        "      },\n" +
                        "      \"functions\": [\n" +
                        "        {\n" +
                        "          \"field_value_factor\": {\n" +
                        "            \"field\": \"like\",\n" +
                        "            \"factor\": 0.3,\n" +
                        "            \"modifier\": \"log1p\",\n" +
                        "            \"missing\": 1\n" +
                        "          }\n" +
                        "        },\n" +
                        "        {\n" +
                        "          \"field_value_factor\": {\n" +
                        "            \"field\": \"click\",\n" +
                        "            \"factor\": 0.1,\n" +
                        "            \"modifier\": \"log1p\",\n" +
                        "            \"missing\": 1\n" +
                        "          }\n" +
                        "        },\n" +
                        "        {\n" +
                        "          \"script_score\": {\n" +
                        "            \"script\": {\n" +
                        "              \"source\": \"doc['score'].value * 0.6\"\n" +
                        "            }\n" +
                        "          }\n" +
                        "        }\n" +
                        "      ],\n" +
                        "      \"boost_mode\": \"sum\"\n" +
                        "    }\n" +
                        "  },\n" +
                        "  \"_source\": [\"filename\", \"like\", \"click\", \"path\", \"documentId\", \"page\",\"uploadUserName\",\"uploadTime\"],\n" +
                        "  \"sort\": [\n" +
                        "    {\"_score\": {\"order\": \"desc\"}}\n" +
                        "  ],\n" +
                        "  \"highlight\": {\n" +
                        "    \"fields\": {\n" +
                        "      \"pdfText\": {\"pre_tags\": [\"<em style='color:red'>\"], \"post_tags\": [\"</em>\"], \"fragment_size\": 50},\n" +
                        "      \"ocrText\": {\"pre_tags\": [\"<em style='color:red'>\"], \"post_tags\": [\"</em>\"], \"fragment_size\": 50}\n" +
                        "    }\n" +
                        "  },\n" +
                        "  \"collapse\": {\n" +
                        "    \"field\": \"documentId\"\n" +
                        "  }\n";


        GetIndexRequest indexRequest = new GetIndexRequest("image");

//        indexRequest.(json(), XContentType.JSON);
//        IndexResponse response = client.index(indexRequest, "fendodate")
//                .setSource(json)
//                .get();
        Map<String, Object> jsonMap = new HashMap<String, Object>();


    }

//    @Test
//    public void testGetListDoc() throws IOException {
//        SearchRequest searchRequest = new SearchRequest("pdftxt", "image");
//        // 构建搜索builder
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//
//        // 构建查询条件(查询所有)
//        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
//
//        // 构建查询条件(精确匹配)
////        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("ocrText", "影响");
//
//        // 把查询条件设置给搜索builder
//        searchSourceBuilder.query(matchAllQueryBuilder);
//
//        // 设置分页查询(跟sql语句的limit一样)
//        searchSourceBuilder.from(0); // 开始下标(当前页码-1)*每页显示条数
//        searchSourceBuilder.size(100); // 要查多少个
//
//        // 设置排序规则
//        searchSourceBuilder.sort("_score", SortOrder.DESC);
//
//        // 把所有条件设置给查询请求
//        searchRequest.source(searchSourceBuilder);
//
//        // 开始查询
//        SearchResponse searchResponse =
//                client.search(searchRequest, RequestOptions.DEFAULT);
//        // 查看结果(结果很多，所以循环)
//        SearchHits hits = searchResponse.getHits();
//        for (SearchHit hit : hits) {
//            System.out.println(hit.getSourceAsString());
//        }
//
//    }

    //高亮查询
//    @Test
//    public void testHighLightDoc() throws IOException {
//        // 构建搜索请求
//        SearchRequest searchRequest = new SearchRequest("pdftxt", "image");
//
//        // 构建搜索条件构造器(也就是总的搜索条件)
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//
//        // 构建单独的一个高亮构建器
//        HighlightBuilder highlightBuilder = new HighlightBuilder();
//        // 设置高亮字段
//        highlightBuilder.preTags("<font color='red'>"); //前缀
//        highlightBuilder.postTags("</font>");   // 后缀
//        highlightBuilder.field("pdfText", 10).field("ocrText", 10);
//        // 把单独的高亮构建器设置给总构建器
//        searchSourceBuilder.highlighter(highlightBuilder);
//        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//        // 把总的搜索条件给到搜索请求中
//        searchRequest.source(searchSourceBuilder);
//        // 执行请求
//        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//        // 打印结果
//        SearchHits hits = searchResponse.getHits();
//        for (SearchHit hit : hits) {
//            System.out.println(hit.getSourceAsString());
//            // 获取对应的高亮域
//            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
//            System.out.println(highlightFields);
//            // 获取对应的高亮字段
//            HighlightField highlightField = highlightFields.get("影像组学");
//            if (highlightField != null) {
//                // 拿到高亮字段的文本域
//                Text[] texts = highlightField.getFragments();
//                String name = "";
//                for (Text text : texts) {
//                    name += text;
//                    // 打印高亮字段
//                    System.out.println(name);
//                }
//            }
//        }
//    }

    // 多条件查询，也叫组合查询
    @Test
    public void testBoolqueryDoc() throws IOException {
//        SearchRequest searchRequest = new SearchRequest("your_index_name");
//
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        sourceBuilder.size(6);
//        sourceBuilder.from(0);
//
//        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//        boolQuery.must(QueryBuilders.multiMatchQuery("your_search_keyword", "ocrText", "pdfText"));
//
//        sourceBuilder.query(QueryBuilders.functionScoreQuery(boolQuery)
//                .add(new FieldValueFactorFunctionBuilder("click").factor(0.3f).missing(0))
//                .add(new FieldValueFactorFunctionBuilder("like").factor(0.1f).missing(0))
//                .boostMode(CombineFunction.SUM)
//                .scoreMode(ScoreMode.SUM));
//
//        HighlightBuilder highlightBuilder = new HighlightBuilder();
//        highlightBuilder.field("pdfText");
//        highlightBuilder.field("ocrText");
//
//        sourceBuilder.highlighter(highlightBuilder);
//
//        Script script = new Script(
//                ScriptType.INLINE, "painless", "_score + doc['your_field'].value", Collections.emptyMap());
//        ScriptField scriptField = new ScriptField("lastscore", script);
//        sourceBuilder.scriptFields(scriptField);
//
//        sourceBuilder.sort(new FieldSortBuilder("lastscore").order(SortOrder.DESC));
//
//        searchRequest.source(sourceBuilder);
//
//        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

    }


    @Test
    public void cursor() throws IOException, ParseException {

//        RestHighLevelClient client = new RestHighLevelClient(
//                RestClient.builder(new HttpHost("localhost", 9200, "http"))
//        );
        SearchRequest searchRequest = new SearchRequest("pdftxt,image");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery("影像组学特征", "ocrText", "pdfText");

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery().must(multiMatchQuery);

        sourceBuilder.query(boolQuery);

        HighlightBuilder highlightBuilder = new HighlightBuilder()
                .field("ocrText")
                .field("pdfText")
                .preTags("<em style='color:red'>")
                .postTags("</em>");

        sourceBuilder.highlighter(highlightBuilder);
        sourceBuilder.size(120);
        sourceBuilder.timeout(TimeValue.timeValueSeconds(10));
        sourceBuilder.collapse(new CollapseBuilder("id"));
        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//        System.out.println(searchResponse);


        ObjectMapper objectMapper = new ObjectMapper();
        Es es = new Es();

// 处理查询结果
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            // 获取原始文档
            String sourceAsString = hit.getSourceAsString();
//            System.out.println("Source: " + sourceAsString);

            JsonNode jsonNode = objectMapper.readTree(sourceAsString);
            // 获取高亮的片段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();


            HighlightField pdfTextHighlightField = highlightFields.get("pdfText");
            HighlightField ocrTextHighlightField = highlightFields.get("ocrText");
            es.setPath(jsonNode.path("path").asText());
            es.setDocumentid(jsonNode.path("documentId").asInt());
            es.setFilename(jsonNode.path("filename").asText());
            es.setLike(jsonNode.path("like").asInt());
            es.setPage(jsonNode.path("page").asInt());
            es.setClick(jsonNode.path("click").asInt());
            es.setRelativeScore(hit.getScore());
            es.setType(hit.getIndex());
            es.setUserid(jsonNode.path("userid").asInt());
            es.setId(jsonNode.path("id").asInt());
            // 解析日期字符串
            Instant instant = Instant.parse(jsonNode.path("uploadTime").asText());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
//            es.setUploadTime(sdf.parse(jsonNode.path("uploadTime").asText()));


            es.setUploadUserName(jsonNode.path("uploadUserName").asText());
            // 检查是否存在pdfText字段的高亮结果
            if (hit.getHighlightFields().containsKey("pdfText")) {
                // 获取pdfText字段的高亮片段
                Text[] pdfTextHighlights = hit.getHighlightFields().get("pdfText").getFragments();
                StringBuilder pdfTextHighlightBuilder = new StringBuilder();
                for (Text highlight : pdfTextHighlights) {
                    pdfTextHighlightBuilder.append(highlight.string());
                }
                es.setPdftext(pdfTextHighlightBuilder.toString());
            }

            // 检查是否存在ocrText字段的高亮结果
            if (hit.getHighlightFields().containsKey("ocrText")) {
                // 获取ocrText字段的高亮片段
                Text[] ocrTextHighlights = hit.getHighlightFields().get("ocrText").getFragments();
                StringBuilder ocrTextHighlightBuilder = new StringBuilder();
                for (Text highlight : ocrTextHighlights) {
                    ocrTextHighlightBuilder.append(highlight.string());
                }
                es.setPdftext(ocrTextHighlightBuilder.toString());
            }


        }


    }

    @Test
    public void creatable() {
        String tableName = "wander";
        esMapper.createSearchTable(tableName);
    }

    @Test
    public void droptable() {
        String tableName = "wander";
        esMapper.dropTable(tableName);
    }

    @Test
    public void search() {

        List<Es> list = esService.search("影像组学特征", 114);
        System.out.println(list);
    }

    @Test
    public void update() throws IOException {


        int id = 343;
        int click = 10;
        String strID = String.valueOf(id);

        UpdateByQueryRequest request = new UpdateByQueryRequest("pdftxt,image");
        request.setQuery(new TermQueryBuilder("documentId", id));
        request.setScript(new Script("ctx._source['click']=" + 10 + ";"));
        try {
            client.updateByQuery(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


}












